home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
lantimes
/
90_03
/
tnet.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-08
|
16KB
|
554 lines
/*-------------------------------------------------------------------------*
* tnet.c -- network client application
*
* The main routine establishes communications with the
* tnet ``server,'' then accepts commands from the user.
* Each command is then serviced by one of the ``cmd_xxx()''
* routines below.
*
* T. Nolan - 11/20/89
*-------------------------------------------------------------------------*/
#include <dos.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "netbios.h"
#include "network.h"
#define NARGS 10 /* max number of command arguments */
int exitflag;
char local[16]; /* node name of local machine */
char remote[16]; /* node name of remote server */
char buf[4096]; /* buffer for file read/write */
extern int nb_errno; /* netbios error return */
/*-------------------------------------------------------------------------*/
main(int ac, char **av)
{
ACTION ncmd, rcmd; /* send and receive cmd blocks */
NCB ncb; /* NetBIOS ncb */
long ltime; /* for timeout */
char *argv[NARGS]; /* array of parsed command args */
int argc; /* number of command args */
char line[80]; /* buffer for command line */
printf("Tnet - T. Nolan 11/20/89\n");
/* Post a receive-datagram, and send out a connect request.
* Use the command-line arg as the server node name and
* request via datagram. Set a 5-second timeout, and wait for
* something to happen.
*/
if(ac == 1)
{
printf("Format is TNET \\\\nodeid");
exit(1);
}
clear_ncb(&ncb);
nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
ncmd.type = NET_CNCT;
ncmd.code = 0;
while(1)
{
time(<ime);
printf("Trying to locate Tnet server...\n");
strcpy(remote, av[1]);
send_datagram(remote, &ncmd, sizeof(ACTION));
while((time(0) < ltime + 5) && !kbhit() && (ncb.cmdcplt == 0xff))
;
/* Figure out what happened. */
if(kbhit()) /* keyboard interrupt */
{
if(!getch())
getch();
nb_cancel(&ncb);
exit(1);
}
if(ncb.cmdcplt != 0xff) /* command completed */
{
if(ncb.retcode)
{
printf("NetBIOS error %x\n", ncb.retcode);
exit(1);
}
if(rcmd.type != NET_CNCT || rcmd.code != NET_ACK)
{
printf("NetBIOS not installed\n");
exit(1);
}
break; /* exit from loop */
}
} /* must have timed out.. try again */
/* If we get here, we've had a successful datagram exchange
* with the server. The server's node name appears in
* the ncb, and our node name appears in the rcmd.
*/
namecpy(remote, ncb.callname);
namecpy(local, rcmd.name);
printf("\Tnet node %s connected to server node %s\n", local, remote);
/* Command loop. Write the prompt, get a command. Split
* the command into its component strings and tokenize
* the command name. Invoke the appropriate handler.
*/
while(!exitflag)
{
printf("\nTnet> "); /* prompt user for command */
gets(line); /* read command line */
argc = reargv(strlwr(line), argv); /* separate arguments */
if(!argc)
continue; /* nothing to do... */
if(*argv[0] == '!') /* "shell out" prefix */
{
argv[0]++;
shell(argc, argv);
continue;
}
switch(parse(argv[0])) /* look at 1st arg */
{
case -1 :
printf("Ambiguous command\n");
cmd_help();
break;
case 0 :
cmd_remote(argc, argv);
break;
case 1 :
cmd_get (argc, argv);
break;
case 2 :
cmd_put (argc, argv);
break;
case 3 :
cmd_chd (argc, argv);
break;
case 4 :
cmd_help(argc, argv);
break;
case 5 :
cmd_bye (argc, argv);
break;
case 6 :
cmd_dir (argc, argv);
break;
case 7 :
case 8 :
cmd_del (argc, argv);
break;
case 9 :
exitflag = 1;
break;
}
}
exit(0);
}
/*-------------------------------------------------------------------------*/
int reargv(char *cmd, char **av) /* turn command line into argc, argv[] */
{
int c;
int inwhite = 1;
int ac;
/* This is a simple lexical scanner that looks for
* white space separating command arguments. Each
* argument found is terminated by a null byte. The
* count and the array of arguments are returned.
*/
for(ac = 0; ac < NARGS; ac++) /* zero all arg pointers */
av[ac] = '\0';
ac = 0; /* zero arg count */
while(*cmd) /* scan the command line */
{
if(inwhite && *cmd != ' ') /* found the start of a word... */
{
inwhite = 0;
av[ac++] = cmd; /* ...so set the next arg pointer */
}
else if(!inwhite && *cmd == ' ') /* found end of a word... */
{
inwhite = 1;
*cmd = '\0'; /* ...so null-terminate it */
}
cmd++;
}
return(ac); /* return count of args found */
}
/*-------------------------------------------------------------------------*/
int parse(char *cmd) /* tokenize the command word */
{
/* This tokenizer finds a command in the table matching the
* given string, and returns its index in the table. It
* returns 0 if no match is found. Abbreviated commands
* are accepted, and -1 is returned if the string matches
* more than one command.
*/
static char *cmd_table[] =
{
"get", /* 1 */
"put", /* 2 */
"cd", /* 3 */
"help", /* 4 */
"kill", /* 5 */
"dir", /* 6 */
"del", /* 7 */
"erase", /* 8 */
"quit", /* 9 */
0
};
int i = 0;
int match = -1;
char **cp = cmd_table;
while(*cp) /* loop through the cmd table */
{
i++;
if(!strncmp(*cp, cmd, strlen(cmd)))
{
if(match != -1)
return(-1); /* ambiguous command */
else
match = i; /* set match index */
}
cp++;
}
if(match == -1)
return(0); /* no match */
else
return(match); /* successful match */
}
/*-------------------------------------------------------------------------*/
cmd_get(int ac, char **av) /* get files from server */
{
ACTION ncmd, rcmd;
NCB ncb;
int len;
int lsn = 0;
FILE *fp;
long size;
if(ac < 2)
{
printf("error - no file name supplied\n");
return;
}
ncmd.type = NET_GET;
ncmd.code = 0;
strcpy(ncmd.name, av[1]);
clear_ncb(&ncb); /* post 1st receive */
nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
send_datagram(remote, &ncmd, sizeof(ACTION)); /* send our request */
while(1)
{
while(ncb.cmdcplt == 0xff)
;
if(rcmd.code == NET_ERR) /* no more files */
break; /* ..so get out */
if(!lsn)
lsn = listen(remote, local); /* establish session */
/* (1st time only) */
size = rcmd.size; /* save file size */
printf("file %s", rcmd.name);
fp = fopen(rcmd.name, "wb"); /* open it */
while(size > 0) /* get the data */
{
printf(".");
len = receive(lsn, buf, sizeof(buf));
if(fp)
fwrite(buf, 1, len, fp);
size -= len;
}
size = rcmd.size; /* save size again */
clear_ncb(&ncb); /* post next receive */
nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
send(lsn, 0, 0); /* ACK this file */
if(fp)
{
printf(" %ld bytes received.\n", size);
fclose(fp);
}
else
printf(" error opening file.\n");
} /* loop for more */
hangup(lsn);
}
/*-------------------------------------------------------------------------*/
cmd_put(int ac, char **av) /* put files to remote server */
{
ACTION ncmd;
NCB ncb;
FILE *fp;
int lsn = 0;
int len;
struct find_t info;
int found;
long size;
char fname[80];
char *dir_end;
if(ac < 2)
{
printf("error - no file spec supplied\n");
return;
}
strcpy(fname, av[1]); /* copy file specification */
dir_end = strrchr(fname, '\\'); /* locate last '\' char */
if(!dir_end) /* none there, so */
dir_end = fname; /* no directory string */
else /* found one, so */
dir_end++; /* point one char past it */
/* find matching file in current working directory */
found = !_dos_findfirst(av[1], _A_NORMAL, &info);
while(found) /* do for all matching files */
{
*dir_end = '\0'; /* prepare to concatenate */
strcat(fname, info.name); /* file name onto dir string */
if((fp = fopen(fname, "rb")) == NULL) /* open file */
break;
ncmd.size = size = info.size; /* extract file size */
strcpy(ncmd.name, info.name); /* copy to cmd blk */
ncmd.type = NET_PUT;
ncmd.code = 0;
clear_ncb(&ncb); /* issue a receive */
nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);
send_datagram(remote, &ncmd, sizeof(ACTION)); /* req put */
while(ncb.cmdcplt == 0xff) /* wait for receive */
;
printf("file %s", fname);
if(ncmd.code == NET_ERR) /* req rejected */
{
printf(" error sending file\n");
continue; /* skip this one */
}
lsn = listen(remote, local); /* establish session */
while(size > 0) /* send the data */
{
printf(".");
len = fread(buf, 1, sizeof(buf), fp);
send(lsn, buf, len);
size -= len;
}
receive(lsn, 0, 0); /* wait for hangup */
fclose(fp); /* close file */
printf(" %ld bytes sent.\n", info.size);
found = !_dos_findnext(&info); /* find next file */
}
}
/*-------------------------------------------------------------------------*/
cmd_chd(int ac, char **av) /* change remote directory */
{
ACTION ncmd;
NCB ncb;
ncmd.type = NET_CHD;
ncmd.code = 0;
strcpy(ncmd.name, av[1]);
clear_ncb(&ncb);
nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
send_datagram(remote, &ncmd, sizeof(ACTION)); /* send chd req */
while(ncb.cmdcplt == 0xff) /* wait for recv */
;
if(ncmd.code != NET_ACK) /* check for error */
printf("directory or drive not found\n");
printf("current directory is %s\n", ncmd.name); /* print cwd */
}
/*-------------------------------------------------------------------------*/
cmd_dir(int ac, char **av) /* remote directory listing */
{
ACTION ncmd;
NCB ncb;
int lsn;
int len;
ncmd.type = NET_DIR;
ncmd.code = 0;
strcpy(ncmd.name, av[1]);
clear_ncb(&ncb);
nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
send_datagram(remote, &ncmd, sizeof(ACTION)); /* send dir request */
while(ncb.cmdcplt == 0xff) /* wait for recv */
;
if(ncmd.code != NET_ACK) /* check for error */
{
printf("error getting directory\n");
return;
}
lsn = listen(remote, local); /* establish session */
while(ncmd.size > 0) /* receive dir list */
{
len = receive(lsn, buf, sizeof(buf));
fwrite(buf, 1, len, stdout); /* put to screen */
ncmd.size -= len;
}
hangup(lsn); /* hang up session */
}
/*-------------------------------------------------------------------------*/
cmd_del(int ac, char **av) /* delete remote files */
{
ACTION ncmd;
NCB ncb;
if(ac < 2)
{
printf("error - no file specified\n");
return;
}
ncmd.type = NET_DEL;
ncmd.code = 0;
strcpy(ncmd.name, av[1]);
clear_ncb(&ncb);
nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
send_datagram(remote, &ncmd, sizeof(ACTION)); /* send del request */
while(ncb.cmdcplt == 0xff) /* wait for recv */
;
printf("%d files deleted\n", ncmd.size); /* print information */
}
/*-------------------------------------------------------------------------*/
cmd_remote(int ac, char **av) /* execute a remote command */
{
ACTION ncmd;
NCB ncb;
char *bp;
ncmd.type = NET_REMOTE;
ncmd.code = 0;
ncmd.size = ac; /* number of args in cmd */
for(bp = ncmd.name; ac; --ac, ++av) /* copy the rest of the args */
{
strcpy(bp, *av);
bp += strlen(*av) + 1;
}
clear_ncb(&ncb);
nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb); /* post receive */
send_datagram(remote, &ncmd, sizeof(ACTION)); /* send cmd req */
while(ncb.cmdcplt == 0xff) /* wait for recv */
;
printf("command returned %d\n",ncmd.code);
}
/*-------------------------------------------------------------------------*/
cmd_bye(void) /* shut down remote server */
{
ACTION ncmd;
char buf[10];
printf("Shut down remote server (y/n): ");
gets(buf);
if(toupper(*buf) == 'Y')
{
ncmd.type = NET_BYE;
ncmd.code = 0;
send_datagram(remote, &ncmd, sizeof(ACTION));
exitflag = 1; /* force this program to exit too */
}
}
/*-------------------------------------------------------------------------*/
shell(int ac, char **av) /* shell out one command and return */
{
char *cmd;
int i;
cmd = getenv("COMSPEC");
if(*av[0]) /* something appears after the !... */
{
ac += 2; /* so fill in command args */
for(i = ac - 1; i >= 2; i--)
av[i] = av[i - 2];
av[0] = cmd; /* 1st arg is command.com pathname */
av[1] = "/C"; /* 2nd arg is /C (transient command) */
av[ac] = 0; /* terminate parameter list */
}
else /* otherwise shell out until exit */
{
av[0] = cmd;
av[1] = 0;
printf("EXIT to return to Tnet\n"); /* remind user */
}
spawnv(P_WAIT, cmd, av);
}
/*-------------------------------------------------------------------------*/
cmd_help() /* help screen */
{
printf( "\n"
" Commands to remote server:\n"
" get <filename>\n"
" put <filename>\n"
" cd <dirname>\n"
" dir <filename>\n"
" del <filename>\n"
" erase <filename>\n"
" kill\n"
"\n"
" Local commands:\n"
" !<command>\n"
" help\n"
" quit\n"
"\n"
" <filename> may contain wildcards\n"
"\n");
}